const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const inquirer = require('inquirer')
const { spawnSync, copySync, installSync, editSync } = require('../utils')
const template = require('../templates/template.json')

module.exports = (args = [], withClear = true) => {
  if (withClear) {
    console.clear()
  }
  const cwd = process.cwd()
  let projectName = args[0]

  const getProjectName = () => {
    return inquirer.prompt([{
      type: 'input',
      name: 'projectName',
      message: '请输入项目名称:',
      validate: (input) => input.trim() !== ''
    }])
  }
  
  const getVersion = () => {
    return inquirer.prompt([{
      type: 'list',
      name: 'version',
      message: '请选择vue版本:',
      default: '2',
      choices: ['2', '3']
    }])
  }
  
  const getIsTs = () => {
    return inquirer.prompt([{
      type: 'confirm',
      name: 'isTs',
      message: '是否需要typescript:',
      default: true
    }])
  }

  /**
   * 更新或下载项目模板
   * @param {string} cwd
   * @param {string} gitUrl
   * @returns {Promise<void>}
   */
  const loadTemplate = (cwd, gitUrl) => {
    return new Promise((resolve) => {
      fs.readdir(cwd, { 'encoding': 'utf-8' }, (err) => {
        let gitArgs, tips
        if (err) {
          gitArgs = ['clone', gitUrl]
          tips = '下载项目模板'
        } else {
          gitArgs = ['pull']
          tips = '更新项目模板'
        }
        console.log(chalk.blue(`\n🛩️  ${tips}...`))
        console.time(chalk.blue(`🛩️  ${tips}完成`))
        spawnSync('git', gitArgs, {
          cwd: !err ? cwd : path.resolve(__dirname, '../templates')
        }).then((res) => {
          if (res !== 0) {
            console.log(chalk.red(`🛩️  ${tips}失败！请检查你的网络是否可用`))
            if (err) {
              // 如果无模板文件
              process.exit()
            }
          } else {
            console.timeEnd(chalk.blue(`🛩️  ${tips}完成`))
            resolve()
          }
        }).catch(() => {
          console.log(chalk.red(`🛩️  ${tips}失败！`))
          process.exit()
        })
      })
    })
  }

  /**
   * 复制内容到新创建的文件目录
   * @param {string} src 被复制的目录
   * @param {string} dest 新文件目录
   */
  const copyTemplate = (src, dest) => {
    return new Promise((resolve) => {
      const messag = chalk.blue('\n🚀 同步模板文件完成')
      console.time(messag)
      copySync(src, dest, ['.git']).then(() => {
        // 修改package.json的name选项
        editSync(path.resolve(dest, './package.json'), (data) => {
          return data.replace(
            /"name": "([a-zA-Z0-9-_]*)"/,
            (val, k) => val.replace(k, projectName)
          ).replace(
            /"version": "([v\.0-9]*)"/,
            (val, k) => val.replace(k, '0.0.1')
          )
        }).then(() => {
          console.timeEnd(messag)
          resolve()
        }).catch(() => {
          console.timeEnd(messag)
          resolve()
        })
      }).catch(() => {
        console.log(chalk.red('🚀 同步模板文件失败！'))
        process.exit()
      })
    })
  }

  const createWorkFolder = (gitUrl) => {
    const projectCwd = path.join(cwd, projectName)
    fs.mkdir(projectCwd, async (err) => {
      if (err) {
        console.log(chalk.red(`\n文件夹 ${projectName} 已存在\n`))
        process.exit()
      }
      const gitName = gitUrl.match(/\/([^\/]+)\.git$/)[1]
      const templatesCwd = path.resolve(__dirname, '../templates/' + gitName)
      await loadTemplate(templatesCwd, gitUrl)
      // 复制内容到新创建的文件目录
      await copyTemplate(templatesCwd, projectCwd)
      console.log(chalk.blue('\n🚗 安装依赖...'))
      console.time(chalk.blue('🚗 安装依赖完成'))
      installSync(projectCwd).then(() => {
        console.timeEnd(chalk.blue('🚗 安装依赖完成'))
        console.log(
          '\nEverything is Done! To get satrt:\n'
          + '=================================\n'
          + `  cd ./${projectName}\n`
          + '  npm run serve\n'
          + '=================================\n'
        )
      }).catch(() => {
        console.log(chalk.red('🚗 安装依赖失败'))
        process.exit()
      })
    })    
  }

  const doNext = () => {
    getVersion().then(({ version }) => {
      if (version === '2') {
        getIsTs().then(({ isTs }) => {
          // vue2
          if (isTs) {
            createWorkFolder(template.vue2.ts)
          } else {
            createWorkFolder(template.vue2.js)
          }
        })
      } else {
        // vue3
        createWorkFolder(template.vue3.js)
      }
    })
  }

  if (!projectName) {
    getProjectName().then(answer => {
      projectName = answer.projectName
      doNext()
    })
  } else {
    doNext()
  }
}